package com.vis.view.ui
{
	import flare.vis.data.Data;
	import flare.vis.data.DataList;
	import flare.vis.data.NodeSprite;
	import flare.vis.operator.layout.CircleLayout;
	
	import flash.geom.Point;
	import flash.geom.Rectangle;
	
	public class CircleTreeLayout extends CircleLayout
	{
		public function CircleTreeLayout()
		{
			super(null, null, true, Data.NODES);
		}
		
		protected override function layout():void {
			var list:DataList = visualization.data.group(_group);
			var i:int = 0, N:int = list.length, dr:Number;
			var visitor:Function = null;
			
			// determine radius
			var b:Rectangle = layoutBounds;
			_outer = Math.min(b.width, b.height)/2 - padding;
			_inner = isNaN(_innerFrac) ? _inner : _outer * _innerFrac;
			
			// set the anchor point
			var anchor:Point = layoutAnchor;
			list.visit(function(n:NodeSprite):void { n.origin = anchor; });
			setTreeAngles();
			
			setTreeRadii();			
			_t.$(visualization.data.tree.root).radius = 0;			
			// finish up
			updateEdgePoints(_t);
		}
		
		private function setTreeAngles():void
		{
			// first pass, determine the angular spacing
			var root:NodeSprite = visualization.tree.root, p:NodeSprite = null;
			var leafCount:int = 0, parentCount:int = 0;
			root.visitTreeDepthFirst(function(n:NodeSprite):void {
				if (n.childDegree == 0) {
					if (p != n.parentNode) {
						p = n.parentNode;
						++parentCount;
					}
					++leafCount;
				}
			});
			//var inc:Number = (-angleWidth) / (leafCount + parentCount); //the original circle layout statement, this caused the gap in circle layout
			var inc:Number = (-angleWidth) / (leafCount); // new circle layout statement for inc.
			var angle:Number = startAngle;
			
			// second pass, set the angles
			root.visitTreeDepthFirst(function(n:NodeSprite):void {
				var a:Number = 0, b:Number;
				if (n.childDegree == 0) {
					if (p != n.parentNode) {
						p = n.parentNode;
						angle += inc;
					}
					a = angle;
					angle += inc;
				} else if (n.parent != null) {
					a = _t.$(n.firstChildNode).angle;
					b = _t.$(n.lastChildNode).angle - a;
					while (b >  Math.PI) b -= 2*Math.PI;
					while (b < -Math.PI) b += 2*Math.PI;
					a += b / 2;
				}
				_t.$(n).angle = minAngle(n.angle, a);
			});
		}
		
		private function setTreeRadii():void
		{
			var n:NodeSprite;
			var depth:Number = 0, dr:Number = _outer - _inner;
			
			for each (n in visualization.tree.nodes) {
				if (n.childDegree == 0) {
					depth = Math.max(n.depth, depth);
					_t.$(n).radius = _outer;
				}
			}
			for each (n in visualization.tree.nodes) {
				if (n.childDegree != 0) {
					_t.$(n).radius = _inner + (n.depth/depth) * dr;
					
				}
			}
			
			n = visualization.tree.root;
			if (!_t.immediate) {
				delete _t._(n).values.radius;
				delete _t._(n).values.angle;
			}
			_t.$(n).x = n.origin.x;
			_t.$(n).y = n.origin.y;
		}
	}
}